#include <iostream>

using std::cout;
using std::endl;

class Complex
{
public:
    Complex(double dreal, double dimage)
    : _dreal(dreal)
    , _dimage(dimage)
    {   cout << "Complex(double,double)" << endl;   }

    void print() const
    {
        cout << _dreal << " + " << _dimage << " i" << endl;
    }

    //友元函数之普通函数
    //推荐使用
    friend Complex operator+(const Complex &, const Complex &);

    //左操作数(对象本身)发生了变化, 其返回值使用了引用形式
    Complex & operator+=(const Complex & rhs)
    {
        cout << "operator+=(const Complex &)" << endl;
        _dreal += rhs._dreal;
        _dimage += rhs._dimage;
        return *this;
    }

    //自增运算符的前置形式
    Complex & operator++()
    {
        ++_dreal;
        ++_dimage;
        return *this;
    }

    //自增运算符的后置形式
    //返回值保存的是变化之前的值,应该让他返回一个对象,不能使用引用
    //对于后置形式中的形参int, 就是第二个参数
    //该参数仅仅只是一个标志位，不需要真的传递参数,是一个特殊的存在
    Complex operator++(int x)
    {//对于后置的写法，添加一个参数,代表他是后置形式
        Complex tmp(*this);
        ++_dreal;
        ++_dimage;
        cout << "x:" << x << endl;
        return tmp;
    }

private:
    double _dreal;
    double _dimage;
};

//运算符重载之友元函数(普通函数)
Complex operator+(const Complex & lhs, const Complex & rhs)
{
    Complex tmp(lhs._dreal + rhs._dreal, lhs._dimage + rhs._dimage);
    return tmp;
}

int main()
{
    int a = 1, b = 2;
    int c = a + b;//内置类型的运算符不能重载
    cout << "c:" << c << endl;

    //后置++:  保存一个变量变化之前的值
    cout << "a++: " << a++ << endl;
    //&(a++);//error, 返回的是临时变量，右值
    cout << "a:" << a << endl;
    //前置++ 
    //通过这个例子，我们发现前置++的效率更高一些
    cout << "++a:" << ++a << endl;
    cout << "&(++a): " << &(++a) << endl;//ok, 返回的就是a
    cout << "&a:" << &a << endl;
    cout << "a:" << a << endl << endl;


    Complex c1(1, 2), c2(3, 4);
    cout << "c1:";
    c1.print();
    cout << "c2:";
    c2.print();

    //现在没有相应的运算符可以使用
    Complex c3 = c1 + c2;
    cout << "c3:";
    c3.print();

    cout << "++c1:";
    (++c1).print();
    cout << endl;

    cout << "c1:";
    c1.print();

    cout << "c1++:";
    (c1++).print();
    cout << "c1:";
    c1.print();


    return 0;
}

